package com.qfedu.edu.exception.handler;

import com.qfedu.edu.exception.notify.observe.base.Subject;
import com.qfedu.edu.result.R;
import com.qfedu.edu.result.ResponseCode;
import static com.qfedu.edu.utils.ThreadPoolUtils.*;
import lombok.extern.slf4j.Slf4j;
import com.qfedu.edu.utils.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.SQLException;

import static com.qfedu.edu.utils.ThreadPoolUtils.getExceptionNotifyExecutor;

/**
 * 全局异常类
 */
@ControllerAdvice
@Slf4j
public class GlobalException extends Exception {


    @Autowired
    private Subject subject;

    /**
     * 业务异常处理
     *
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public R handlerBusinessException(BusinessException businessException) {
        R r = R.error(businessException.getCode(), businessException.getMessage());
        return r;
    }

    /**
     * SQL异常处理
     *
     * @param sqlException
     * @return
     */
    @ExceptionHandler(SQLException.class)
    @ResponseBody
    public R handlerSQLException(SQLException sqlException) {
        R r = R.error(ResponseCode.SQL_EXCEPTION);
        return r;
    }

    /**
     * 认证异常处理(没有权限访问的异常)
     * @param accessDeniedException
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseBody
    public R handlerAccessDeniedExceptionException(AccessDeniedException accessDeniedException) {
        R r = R.error(ResponseCode.NO_PERMISSION_EXCEPTION);
        return r;
    }

    /**
     * 系统异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R handlerSystemException(Exception e) {
        R r = R.error(ResponseCode.SYSTEM_EXCEPTION);
        log.error("系统异常："+ ExceptionUtils.getExceptionStackInfo(e));
        // 异步通知管理员 观察者设计模式
        getExceptionNotifyExecutor().execute(() -> {
            subject.notifyMessage(ExceptionUtils.getExceptionStackInfo(e));
        });
        return r;
    }
}
